package aole.mindfx.model;

import java.util.Collection;
import java.util.HashMap;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import aole.mindfx.FXNodeListener;

public class MindFXClass extends MindFXNode implements
		EventHandler< ActionEvent > {
	private HashMap< String, MindFXMethod >		methods		= new HashMap<>();
	private HashMap< String, MindFXAttribute >	attributes	= new HashMap<>();

	private String								headerFile;
	private String								sourceFile;

	private VBox								container	= new VBox( 4 );
	private VBox								atribcont	= new VBox( 2 );
	private VBox								methcont	= new VBox( 2 );
	private FXNodeListener						listener;

	static Font									f			= new Font(
																	"Cambria",
																	20 );

	public static String getStyle() {
		return "-fx-base:red";
	}

	public static Font getFont() {
		return f;
	}

	public String getHeaderFile() {
		return headerFile;
	}

	public void setHeaderFile( String headerFile ) {
		this.headerFile = headerFile;
	}

	public String getSourceFile() {
		return sourceFile;
	}

	public void setSourceFile( String sourceFile ) {
		this.sourceFile = sourceFile;
	}

	public MindFXClass( String n, FXNodeListener l ) {
		super( n );
		headerFile = n + ".h";
		sourceFile = n + ".cpp";
		listener = l;

		Button b = new Button( n );
		b.setStyle( getStyle() );
		b.setFont( getFont() );
		b.setOnAction( this );
		container.getChildren().add( b );

		TitledPane pa = new TitledPane( "Attributes", atribcont );
		container.getChildren().add( pa );
		TitledPane pm = new TitledPane( "Methods", methcont );
		container.getChildren().add( pm );
	}

	public MindFXAttribute getAttribute( String name ) {
		return attributes.get( name );
	}

	public MindFXMethod getMethod( String name ) {
		return methods.get( name );
	}

	public void addFXMethod( MindFXMethod m ) {
		methods.put( m.getName(), m );
		methcont.getChildren().add( m.getFXNode() );
	}

	public void addFXAttribute( MindFXAttribute a ) {
		attributes.put( a.getName(), a );
		atribcont.getChildren().add( a.getFXNode() );
	}

	public Collection< MindFXMethod > getMethods() {
		return methods.values();
	}

	public Collection< MindFXAttribute > getAttributes() {
		return attributes.values();
	}

	@Override
	public Node getFXNode() {
		return container;
	}

	@Override
	public boolean setXMLAttribute( String att, String value ) {
		if( super.setXMLAttribute( att, value ) ) return true;

		switch( att ) {
		case "header":
			headerFile = value;
			return true;
		case "source":
			sourceFile = value;
			return true;
		}
		return false;
	}

	@Override
	public void handle( ActionEvent event ) {
		listener.actionPerformed( this );
	}

	@Override
	public void saveXML( Document doc, Element e ) {
		// add attributes
		Element a = doc.createElement( "attributes" );
		a.setAttribute( "count", "" + attributes.size() );
		e.appendChild( a );
		for( MindFXAttribute att: attributes.values() ) {
			Element attr = doc.createElement( att.getName() );
			att.saveXML( doc, attr );
			a.appendChild( attr );
		}

		// add methods
		Element m = doc.createElement( "methods" );
		m.setAttribute( "count", "" + methods.size() );
		e.appendChild( m );
		for( MindFXMethod met: methods.values() ) {
			Element el = doc.createElement( met.getName() );
			met.saveXML( doc, el );
			m.appendChild( el );
		}
	}

	public void loadXML( org.w3c.dom.Node node ) {
		Element e = (Element) node;
		// load attributes
		NodeList nList = e.getElementsByTagName( "attributes" );
		org.w3c.dom.Node firstnode = nList.item( 0 );
		if( firstnode != null ) {
			for( org.w3c.dom.Node att = firstnode.getFirstChild(); att != null; att = att
					.getNextSibling() ) {
				if( att.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE ) {
					String name = att.getNodeName();
					MindFXAttribute a = new MindFXAttribute( name, listener,
							this );
					addFXAttribute( a );
					a.loadXML( att );
				}
			}
		}
		// load methods
		nList = e.getElementsByTagName( "methods" );
		firstnode = nList.item( 0 );
		if( firstnode != null ) {
			for( org.w3c.dom.Node met = firstnode.getFirstChild(); met != null; met = met
					.getNextSibling() ) {
				if( met.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE ) {
					String name = met.getNodeName();
					MindFXMethod m = new MindFXMethod( name, listener, this );
					addFXMethod( m );
					m.loadXML( met );
				}
			}
		}
	}

	@Override
	public Button getCodeButton() {
		Button b = new Button(getName());
		b.setOnAction( this );
		return b;
	}

	public void deleteFXMethod( MindFXMethod m ) {
		methcont.getChildren().remove( m.getFXNode() );
		methods.remove( m.getName() );
		listener.actionPerformed( this );
	}

	public void deleteFXAttribute( MindFXAttribute a ) {
		atribcont.getChildren().remove( a.getFXNode() );
		attributes.remove( a.getName() );
		listener.actionPerformed( this );
	}

}
